package com.sigmatrix.h5.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.log4j.MDC;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.microsoft.windowsazure.exception.ServiceException;
import com.sigmatrix.h5.entity.DisDealer;
import com.sigmatrix.h5.entity.DisDealerAcct;
import com.sigmatrix.h5.entity.DisDealerAcctRegAudit;
import com.sigmatrix.h5.entity.DisRebateActivity;
import com.sigmatrix.h5.entity.DisRebateScanCode;
import com.sigmatrix.h5.entity.DisTerminalShop;
import com.sigmatrix.h5.enums.ApplyStatus;
import com.sigmatrix.h5.enums.ApplyType;
import com.sigmatrix.h5.enums.CoordType;
import com.sigmatrix.h5.enums.CrmAcctType;
import com.sigmatrix.h5.enums.PromotionCodeType;
import com.sigmatrix.h5.exception.MessageException;
import com.sigmatrix.h5.properties.AutoAuditProperties;
import com.sigmatrix.h5.properties.AutoAuditProperties.Module;
import com.sigmatrix.h5.service.DisDealerAcctRegAuditService;
import com.sigmatrix.h5.service.DisDealerAcctService;
import com.sigmatrix.h5.service.DisDealerService;
import com.sigmatrix.h5.service.DisRebateActivityService;
import com.sigmatrix.h5.service.DisRebateAuditService;
import com.sigmatrix.h5.service.DisRebateScanCodeService;
import com.sigmatrix.h5.service.DisTerminalShopDetailService;
import com.sigmatrix.h5.service.DisTerminalShopService;
import com.sigmatrix.h5.service.TerminalRebateService;
import com.sigmatrix.h5.utils.Assert;
import com.sigmatrix.h5.utils.CommonUtils;
import com.sigmatrix.h5.utils.Constants;
import com.sigmatrix.h5.utils.SessionUtils;
import com.sigmatrix.h5.utils.ThreadPool;
import com.sigmatrix.h5.utils.baidu.BaiduMapUtils;
import com.sigmatrix.h5.utils.baidu.po.LatLngLocation;
import com.sigmatrix.h5.web.args.RegistTerminalShopParam;
import com.sigmatrix.h5.web.mode.RebateActivityInfo;
import com.sigmatrix.h5.web.mode.RebateRecord;
import com.sigmatrix.h5.web.mode.RebateRecord.Rebate;

/**
 * 
 *@ClassName: TerminalRebateServiceImpl
 *@Description: 终端返利
 *@author MH
 *@date 2017年12月8日 下午6:03:41
 */
@Service
public class TerminalRebateServiceImpl implements TerminalRebateService{
	Logger logger = Logger.getLogger("REBATELOG");
	@Autowired
	private DisRebateActivityService disRebateActivityService;
	@Autowired
	private DisRebateScanCodeService disRebateScanCodeService;
	@Autowired
	private DisDealerService disDealerService;
	@Autowired
	private DisRebateAuditService disRebateAuditService;
	@Autowired
	private DisTerminalShopService disTerminalShopService;
	@Autowired
	private DisDealerAcctRegAuditService disDealerAcctRegAuditService;
	@Autowired
	private DisDealerAcctService disDealerAcctService;
	@Autowired(required=false)
	private AutoAuditProperties autoAuditProperties;
	@Autowired
	private DisTerminalShopDetailService disTerminalShopDetailService;
	/**
	 * 
	 *@Title: scanCode
	 *@Description:与之前不同的是，不同的openId可以申请相同的店名
	 *@author MH
	 *@date 2018年1月23日 上午10:08:48
	 */
	@Override
	@Transactional
	public DisTerminalShop scanCode(RegistTerminalShopParam param){
		LatLngLocation location = BaiduMapUtils.parseLatAndLng(param.getLat(), param.getLng(),CoordType.GCJ02LL);
		List<DisDealer> list = disDealerService.findParentsByPromotionCode(param.getPromotionCode());
		Short promotionCodeType = PromotionCodeType.DEALER.value;
		if(CommonUtils.isEmpty(list)) {
			list = findDealersByCrmAcctPromotionCode(param.getPromotionCode());
			promotionCodeType = PromotionCodeType.SALES_MAN.value;
		}
		DisDealer writeBackDealer = getWriteBackDealer(list, param.getPromotionCode());
		//校验是否窜货
		if(CommonUtils.isNotEmpty(writeBackDealer)) {
			Assert.notNull(location, "GPS定位失败");
			boolean fleeing = disDealerService.checkFleeing(writeBackDealer.getId(), location);
			if(!fleeing)throw new MessageException("GPS定位的地点没有在该经销商的销售区域内");
		}
		//查看该openId有没有注册过
		DisTerminalShop shop = findRegistRecord(param, writeBackDealer);
		
		//返利
		RebateRecord rebateRecord = doRebate(list,writeBackDealer,promotionCodeType, param);
		
		if(CommonUtils.isEmpty(shop)) {
			shop = new DisTerminalShop();
			BeanUtils.copyProperties(param, shop);
			disTerminalShopService.gpsLoaction(shop);
			Integer id = registShop(writeBackDealer, shop, param);
			shop.setId(id);
		}
		
		//保存一条扫码记录
		saveScanRecord(writeBackDealer, shop.getId(), param);
		
		//大数据需要的日志
		rebateRecord.setEseCode(SessionUtils.getEseCode());
		rebateRecord.setDomain(param.getDomain());
		rebateRecord.setSubDomain(param.getSubDomain());
		rebateRecord.setSeqNum(param.getSeqNum()+"");
		rebateRecord.setScanId(shop.getId());
		rebateRecord.setScanType(CrmAcctType.TERMINAL_SHOP.value);
		rebateRecord.setProductId(param.getProductId());
		rebateRecord.setOpenId(param.getOpenId());
		rebateRecord.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		
		logBigData(rebateRecord);
		
		return shop;
	}
	
	@Deprecated
	private void bigDataLog(String domain,String subDomain,String seqNum,Integer shopId,String openId,List<Rebate> rebates,Integer productId){
		MDC.put("log_type", "scan_type");
		logger.info(JSONObject.toJSONString(new RebateRecord(SessionUtils.getEseCode(),domain,subDomain,seqNum,shopId,productId, CrmAcctType.TERMINAL_SHOP.value, openId, rebates)));
		MDC.clear();
	}
	
	/**
	 * 返利记录。
	 * 
	 * @param rebateRecord
	 */
	private void logBigData(RebateRecord rebateRecord){
		MDC.put("log_type", "scan_type");
		logger.info(JSONObject.toJSONString(rebateRecord));
		MDC.clear();
	}
	
	private DisDealer getWriteBackDealer(List<DisDealer> list ,String promotionCode) {
		return list.stream()
				.sorted((a,b) -> (b.getLevel()==null?0:b.getLevel()) - (a.getLevel()==null?0:a.getLevel()))
				.findFirst().orElse(null);
				//		for (DisDealer d : list) {
//			if(promotionCode.equals(d.getPromotionCode())){
//				return d;
//			}
//		}
//		return null;
	}
	private List<DisDealer> findDealersByCrmAcctPromotionCode(String promotionCode){
		DisDealerAcct acct = disDealerAcctService.findByPromotionCode(promotionCode);
		Assert.notNull(acct, "推广码错误");
		List<DisDealer> list = disDealerService.findParents(acct.getDealerId());
		Assert.notNull(list, "业务员没有经销商信息");
		return list;
	}
	private DisTerminalShop findRegistRecord(RegistTerminalShopParam param,DisDealer writeBackDealer) {
		//校验码是否被扫过
		List<DisRebateScanCode> history = disRebateScanCodeService.findScanHistory(param.getUrlDomain(), param.getSeqNum()+"");
		if(CommonUtils.isNotEmpty(history))throw new MessageException("该码已经被扫过");
		Integer dealerId = null;
		if(CommonUtils.isNotEmpty(writeBackDealer)) {
			dealerId = writeBackDealer.getId();
		}
		DisTerminalShop shop = getShop(param.getOpenId(), param.getName(), dealerId);
		if(CommonUtils.isEmpty(shop)) {
			//看有没有提交过审核
			List<DisDealerAcctRegAudit> regists = disDealerAcctRegAuditService.findRegistShopByOpenId(param.getOpenId());
			if(CommonUtils.isNotEmpty(regists)) {
				for (DisDealerAcctRegAudit audit : regists) {
					if(param.getName().equals(audit.getTerminalName())) {
						boolean f = (CommonUtils.isEmpty(dealerId) && CommonUtils.isEmpty(audit.getDealerId()))||
								(CommonUtils.isNotEmpty(dealerId) && dealerId.equals(audit.getDealerId()));
						if(f) {
							if(ApplyStatus.NO_AUDIT.value.equals(audit.getStatus()) || ApplyStatus.AGREE.value.equals(audit.getStatus())) {
								return disTerminalShopService.findByCode(audit.getAccount());
							}	
						}
					}
				}
			}
		}
		return  shop;
	}
	private DisTerminalShop getShop(String openId,String name,Integer dealerId) {
		//查询该openId注册过的所有门店
		List<DisTerminalShop> shops = disTerminalShopService.findByOpenId(openId);
		if(CommonUtils.isNotEmpty(shops)) {
			for (DisTerminalShop shop : shops) {
				if(name.equals(shop.getName())) {
					boolean f = (CommonUtils.isNotEmpty(dealerId) && dealerId.equals(shop.getDealerId()))||
							(CommonUtils.isEmpty(dealerId)&& CommonUtils.isEmpty(shop.getDealerId()));
					if(f) return shop;
				}
			}
		}
		return null;
	}
	
	/**
	 * 
	 *@Title: scanCode
	 *@Description:该方法不允许终端门店重复
	 *@return DisTerminalShop
	 *@author MH
	 *@date 2018年1月23日 上午10:08:15
	 *@param writeBackDealer
	 *@param param
	 *@return
	 */
	@Deprecated
	public DisTerminalShop scanCode(List<DisDealer> dealers,DisDealer writeBackDealer, RegistTerminalShopParam param) {
		//校验码是否被扫过
		List<DisRebateScanCode> history = disRebateScanCodeService.findScanHistory(param.getUrlDomain(), param.getSeqNum()+"");
		if(CommonUtils.isNotEmpty(history))throw new MessageException("该码已经被扫过");
		//校验是否窜货
		LatLngLocation location = BaiduMapUtils.parseLatAndLng(param.getLat(), param.getLng(),CoordType.GCJ02LL);
		Assert.notNull(location, "GPS定位失败");
		boolean fleeing = disDealerService.checkFleeing(writeBackDealer.getId(), location);
		if(!fleeing)throw new MessageException("GPS定位的地点没有在该经销商的销售区域内");
		//查询该openId是否在该经销商下有终端店
		DisTerminalShop shop = disTerminalShopService.findByOpenIdAndDealerId(param.getOpenId(), writeBackDealer.getId());
		boolean regist = true;
		if(CommonUtils.isEmpty(shop) || !param.getName().equals(shop.getName())){
			regist = false;
			//如果没有的话，查看该终端店是否存在
			shop = disTerminalShopService.findByName(param.getName());
		}
		rebate(dealers,writeBackDealer,PromotionCodeType.DEALER.value, param);//返利
		if(regist) return shop;//如果之前注册过，就返回之前注册的门店
		//如果中断门店已经存在，就只提交申请，不用创建新的终端店
		if(CommonUtils.isNotEmpty(shop)){
			DisDealerAcctRegAudit shopAudit = disDealerAcctRegAuditService.findRegistShopByAccountAndDealerId(shop.getCode(), writeBackDealer.getId());
			//如果之前是驳回就把状态改为未审核
			if(CommonUtils.isNotEmpty(shopAudit)){
				if(ApplyStatus.REJECT.value == shopAudit.getStatus()){
					disDealerAcctRegAuditService.submitAgin(shopAudit.getId(), shopAudit.getAccount());
				}
			}else{
				apply(shop, writeBackDealer,CommonUtils.isNotEmpty(autoAuditProperties) && autoAuditProperties.auto(SessionUtils.getEseCode(), Module.shop));//如果之前没有审批记录，就提新的交审批
			}
			return shop;
		}
		shop = new DisTerminalShop();
		BeanUtils.copyProperties(param, shop);
//		disTerminalShopService.gpsLoaction(shop, location);
		disTerminalShopService.gpsLoaction(shop);
		registShop(writeBackDealer, shop, param);
		//保存一条扫码记录
		saveScanRecord(writeBackDealer,shop.getId(), param);
		return shop;
	}
	/**
	 * 
	 *@Title: rebate
	 *@Description: 返利
	 *@return void
	 *@author MH
	 *@date 2017年12月9日 下午2:49:56
	 *@param dealers
	 *@param writeBackDealer
	 *@param param
	 *@throws ServiceException
	 */
	@Deprecated
	private List<Rebate> rebate(List<DisDealer> dealers,DisDealer writeBackDealer, Short promotionCodeType,RegistTerminalShopParam param){
		//找出一级经销商
		Integer firstLevelDealerId = -1;
		for (DisDealer dealer : dealers) {
			if(Short.valueOf("1").equals(dealer.getLevel()) || CommonUtils.isEmpty(dealer.getParentId()) || dealer.getParentId().equals(-1)){
				firstLevelDealerId = dealer.getId();
				break;
			}
		}
		//先要确定返利活动
		RebateActivityInfo info = disRebateActivityService.determineActivityForTerminalRebate(firstLevelDealerId, param.getProductId(),param.getOpenId(),writeBackDealer.getId());
		if(CommonUtils.isNotEmpty(info)){
			DisRebateActivity activity = disRebateActivityService.getActivity(info);
			return disRebateAuditService.apply(activity,param.getName(), writeBackDealer.getLevel(),param.getPromotionCode(),promotionCodeType,dealers.toArray(new DisDealer[dealers.size()]));
		}
		return null;
	}
	
	/**
	 * 返利
	 * 
	 * @param dealers
	 * @param writeBackDealer
	 * @param promotionCodeType
	 * @param param
	 * @return
	 */
	private RebateRecord doRebate(List<DisDealer> dealers,DisDealer writeBackDealer, Short promotionCodeType,RegistTerminalShopParam param){
		//找出一级经销商
		Integer firstLevelDealerId = -1;
		for (DisDealer dealer : dealers) {
			if(Short.valueOf("1").equals(dealer.getLevel()) || CommonUtils.isEmpty(dealer.getParentId()) || dealer.getParentId().equals(-1)){
				firstLevelDealerId = dealer.getId();
				break;
			}
		}
		//先要确定返利活动
		RebateActivityInfo info = disRebateActivityService.determineActivityForTerminalRebate(firstLevelDealerId, param.getProductId(),param.getOpenId(),writeBackDealer.getId());
		RebateRecord rebateRecord = new RebateRecord(); 
		rebateRecord.setPromotionId(info.getId());
		if(CommonUtils.isNotEmpty(info)){
			DisRebateActivity activity = disRebateActivityService.getActivity(info);
			List<Rebate> rebateItems = disRebateAuditService.apply(activity,param.getName(), writeBackDealer.getLevel(),param.getPromotionCode(),promotionCodeType,dealers.toArray(new DisDealer[dealers.size()]));
			rebateRecord.setRebates(rebateItems);
			return rebateRecord;
		}
		return rebateRecord;
	}
	
	/**
	 * 
	 *@Title: saveScanRecord
	 *@Description: 保存扫码记录
	 *@return void
	 *@author MH
	 *@date 2017年12月9日 下午2:50:11
	 *@param dealer
	 *@param activityId
	 *@param param
	 *@throws ServiceException
	 */
	private void saveScanRecord(DisDealer dealer,Integer shopId,RegistTerminalShopParam param){
		DisRebateScanCode _scan = new DisRebateScanCode();
		_scan.setPromotionCode(param.getPromotionCode());
		_scan.setUrlDomain(param.getUrlDomain());
		_scan.setOpenId(param.getOpenId());
		_scan.setQrCode(param.getTagCode());
		_scan.setRebateActivityId(param.getRebateActivityId());
		_scan.setSeqNum(param.getSeqNum()+"");
		_scan.setAccount(SessionUtils.getAccount());
		_scan.setDealerId(dealer.getId());
		_scan.setDealerCode(dealer.getCode());
		_scan.setProductId(param.getProductId());
		_scan.setScanId(shopId);
		_scan.setScanType(CrmAcctType.TERMINAL_SHOP.value);
		_scan.setStatus(Constants.STATUS_ENABLE);
		_scan.setCodeType(Constants.CODE_TYPE_X);
		_scan.setScanTime(new Date());
		disRebateScanCodeService.insertSelective(_scan);
	}
//	private void validateShop(RegistTerminalShopParam param,Integer dealerId,DisTerminalShop shop){
//		int i;
//		if(CommonUtils.isNotEmpty(shop)){
//			i = disTerminalShopDetailService.selectCountByDealerIdAndShopId(dealerId, shop.getId());
//			if(i > 0)throw new MessageException("该终端店已经注册过");
//		}
//		i = disTerminalShopDetailService.selectCountByOpenId(param.getOpenId(), dealerId);
//		if(i > 0)throw new MessageException("您已经在该经销商注册过终端门店");
//	}
	
	private Integer registShop(DisDealer dealer,DisTerminalShop shop,RegistTerminalShopParam param){
		//保存shop
		if(CommonUtils.isNotEmpty(dealer)) {
			shop.setDealerId(dealer.getId());
		}
		boolean auto = false;
		if(CommonUtils.isNotEmpty(autoAuditProperties) && autoAuditProperties.auto(SessionUtils.getEseCode(), Module.shop)){
			shop.setStatus(Constants.STATUS_ENABLE);
			auto = true;
		}else{
			shop.setStatus(Constants.TERMINAL_SHOP_STATUS_NO_AUDIT);
		}
		//企业ID
		shop.setEnterpriseId(SessionUtils.getEseId());
		final String code = disTerminalShopService.genShopCode();
		//设置默认参数
		shop.setCode(code);
		shop.setCreateTime(new Date());
		Integer id = disTerminalShopService.insertSelective(shop);
		//提交审批
		apply(shop, dealer,auto,param.getPromotionCode());
		return id;
	}
	@Override
	public void apply(DisTerminalShop shop,DisDealer dealer,boolean autoAudit){
		DisDealerAcctRegAudit audit = new DisDealerAcctRegAudit();
		if(CommonUtils.isNotEmpty(dealer)) {
			audit.setDealerId(dealer.getId());
			audit.setDealerName(dealer.getName());
		}
		audit.setApplyType(ApplyType.SHOP.value);
		if(autoAudit){
			audit.setStatus(ApplyStatus.AGREE.value);
		}else{
			audit.setStatus(ApplyStatus.NO_AUDIT.value);
		}
		audit.setAccount(shop.getCode());
		audit.setContact(shop.getMobilePhone());
		audit.setTerminalName(shop.getName());
		audit.setName(shop.getContact());
		audit.setOpenId(shop.getOpenId());
		audit.setRemarks(shop.getRemarks());
		audit.setApplyTime(new Date());
		disDealerAcctRegAuditService.insertSelective(audit);
		if(autoAudit){
			ThreadPool.submit(Void ->{disTerminalShopDetailService.create(shop, audit.getDealerId(), audit.getOpenId());});
		}
	}
	@Override
	public void apply(DisTerminalShop shop, DisDealer dealer, boolean autoAudit, String promotionCode) {
		DisDealerAcctRegAudit audit = new DisDealerAcctRegAudit();
		if(CommonUtils.isNotEmpty(dealer)) {
			audit.setDealerId(dealer.getId());
			audit.setDealerName(dealer.getName());
		}
		audit.setApplyType(ApplyType.SHOP.value);
		if(autoAudit){
			audit.setStatus(ApplyStatus.AGREE.value);
		}else{
			audit.setStatus(ApplyStatus.NO_AUDIT.value);
		}
		audit.setAccount(shop.getCode());
		audit.setContact(shop.getMobilePhone());
		audit.setTerminalName(shop.getName());
		audit.setName(shop.getContact());
		audit.setOpenId(shop.getOpenId());
		audit.setRemarks(shop.getRemarks());
		audit.setApplyTime(new Date());
		audit.setPromotionCode(promotionCode);
		disDealerAcctRegAuditService.insertSelective(audit);
		if(autoAudit){
			ThreadPool.submit(Void ->{disTerminalShopDetailService.create(shop, audit.getDealerId(), audit.getOpenId());});
		}
		
	}
	
}
